package heap

import (
	. "jvm/typedef"
	"math"
)

type Object struct {
	class *Class
	data  interface{}
}

func newObject(class *Class) *Object {
	obj := &Object{
		class: class,
		data:  newSlots(class.instanceSlotCount),
	}
	return obj
}

// 根据name和descriptor设置对象某一字段的值
func (self *Object) SetRefVar(name string, descriptor string, ref *Object) {
	field := self.class.getField(name, descriptor, false)
	slots := self.data.(Slots)
	slots.SetRef(field.slotId, ref)
}

// 根据name和descriptor获取对象某一字段的值
func (self *Object) GetRefVar(name string, descriptor string) *Object {
	field := self.class.getField("value", "[C", false)
	return self.data.(Slots).GetRef(field.slotId)
}

// getter
func (self *Object) Fields() Slots {
	return self.data.(Slots)
}
func (self *Object) Class() *Class {
	return self.class
}

// 判断对象是否是类的实例
func (self *Object) IsInstanceOf(class *Class) bool {
	return class.isAssignableFrom(self.class)
}

// *******************************************************
type Slot struct {
	num U4
	ref *Object
}

// *******************************************************
type Slots []Slot

func newSlots(size U4) Slots {
	return make(Slots, size)
}

// set and get
// *******************************************************
func (self Slots) SetInt(index U4, val I4) {
	self[index].num = U4(val)
}
func (self Slots) GetInt(index U4) I4 {
	return I4(self[index].num)
}

// *******************************************************
// 大端模式存储Long，Double
func (self Slots) SetLong(index U4, val I8) {
	u64 := U8(val)
	self[index].num = U4(u64 >> 32)
	self[index+1].num = U4(u64 & 0xffffffff)
}
func (self Slots) GetLong(index U4) I8 {
	high := (U8(self[index].num)) << 32
	low := (U8(self[index+1].num))
	return I8(high | low)
}

// *******************************************************
func (self Slots) SetFloat(index U4, val F4) {
	bits := math.Float32bits(float32(val))
	self[index].num = U4(bits)
}
func (self Slots) GetFloat(index U4) F4 {
	val := math.Float32frombits(uint32(self[index].num))
	return F4(val)
}

//*******************************************************

func (self Slots) SetDouble(index U4, val F8) {
	num := I8(math.Float64bits(float64(val)))
	self.SetLong(index, num)
}
func (self Slots) GetDouble(index U4) F8 {
	bits := self.GetLong(index)
	val := math.Float64frombits(uint64(bits))
	return F8(val)
}

//*******************************************************

func (self Slots) SetRef(index U4, ref *Object) {
	self[index].ref = ref
}
func (self Slots) GetRef(index U4) *Object {
	return self[index].ref
}
